package net.neptech.listener;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.log.StaticLog;
import net.neptech.model.dto.InstanceExecutionDto;
import net.neptech.model.dto.InstanceNodeRecordParamDto;
import net.neptech.model.dto.node.Node;
import net.neptech.node.NodeDataStoreFactory;
import net.neptech.service.RemoteService;
import net.neptech.util.FlowableUtil;
import net.neptech.util.JsonUtil;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.RuntimeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;

import java.util.Map;

import static net.neptech.enums.workflow.InstanceConstant.VariableKey.NODE_JUMP_KEY;
import static net.neptech.enums.workflow.InstanceConstant.VariableKey.REDIS_KEY_OF_FLOW_UNIQUE_ID;

/**
 * @Author Saya
 * @Date 2025/8/22 14:40
 * @Description TODO
 **/
@Component
public abstract class AbstractEventListenerStrategy implements EventListenerStrategy {
    @Autowired
    private RemoteService remoteService;

    @Override
    public void afterPropertiesSet(String key) {
        EventListenerStrategyFactory.register(key, this);
    }
    @Override
    abstract public void handle(FlowableEvent event);

    @Override
    public void saveStartEventContent(String flowId, String processInstanceId, String activityId, String activityName, String executionId, String tenantId, String parentExecutionId) {
        RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class);
        Map<String, Object> processVariables = runtimeService.getVariables(executionId);
        Node node = NodeDataStoreFactory.getInstance().getNode(flowId, activityId);
        InstanceNodeRecordParamDto InstanceNodeRecordParamDto = new InstanceNodeRecordParamDto();
        InstanceNodeRecordParamDto.setFlowId(flowId);
        InstanceNodeRecordParamDto.setProcessInstanceId(processInstanceId);
        InstanceNodeRecordParamDto.setData(JsonUtil.toJSONString(processVariables));
        InstanceNodeRecordParamDto.setNodeId(activityId);
        String parentNodeId = MapUtil.getStr(processVariables, StrUtil.format(NODE_JUMP_KEY, activityId));
        InstanceNodeRecordParamDto.setParentNodeId(parentNodeId);
        RedisTemplate redisTemplate = SpringUtil.getBean("redisTemplate", RedisTemplate.class);
        if (StrUtil.isNotBlank(parentNodeId)) {
            //跳转过来的
            String s = IdUtil.fastSimpleUUID();
            ZSetOperations zSetOperations = redisTemplate.opsForZSet();
            zSetOperations.add(StrUtil.format(REDIS_KEY_OF_FLOW_UNIQUE_ID, processInstanceId), StrUtil.format("{}||||{}", activityId, s), System.currentTimeMillis());
            InstanceNodeRecordParamDto.setFlowUniqueId(s);
        } else {
            String flowUniqueId = FlowableUtil.getFlowUniqueId(activityId, flowId, processInstanceId, tenantId);
            InstanceNodeRecordParamDto.setFlowUniqueId(flowUniqueId);
        }
        if (node != null) {
            InstanceNodeRecordParamDto.setNodeType((node.getType()));
        }
        InstanceNodeRecordParamDto.setNodeName(activityName);
        InstanceNodeRecordParamDto.setExecutionId(executionId);
        remoteService.startNodeEvent(InstanceNodeRecordParamDto);
        //保存执行信息
        InstanceExecutionDto instanceExecutionDto = new InstanceExecutionDto();
        instanceExecutionDto.setExecutionId(executionId);
        instanceExecutionDto.setParentIdExecutionId(parentExecutionId);
        instanceExecutionDto.setProcessInstanceId(processInstanceId);
        instanceExecutionDto.setNodeId(activityId);
        instanceExecutionDto.setFlowId(flowId);
        remoteService.saveExecution(instanceExecutionDto);
        StaticLog.info("节点开始了： {} {}  {} ", flowId, executionId, activityName);
        //清除变量
        runtimeService.removeVariable(executionId, StrUtil.format(NODE_JUMP_KEY, activityId));
    }
}
